---
title: Readables
icon: "lucide/BookA"
description: Share app specific context with your agent.
---
import RunAndConnect from "@/snippets/integrations/microsoft-agent-framework/run-and-connect.mdx"

One of the most common use cases for CopilotKit is to register app state and context using `useCopilotReadable`.
This way, you can notify CopilotKit of what is going in your app in real time.
Some examples might be: the current user, the current page, etc.

This context can then be shared with your AG-UI server and agent logic.

## Implementation
<Callout>
    Check out the [Frontend Data documentation](https://docs.copilotkit.ai/direct-to-llm/guides/connect-your-data/frontend) to understand what this is and how to use it.
</Callout>

<Steps>
    <Step>
      <RunAndConnect />
    </Step>
    <Step>
        ### Add the data to the Copilot

        The [`useCopilotReadable` hook](/reference/hooks/useCopilotReadable) is used to add data as context to the Copilot.

        ```tsx title="YourComponent.tsx" showLineNumbers {1, 7-10}
        "use client" // only necessary if you are using Next.js with the App Router. // [!code highlight]
        import { useCopilotReadable } from "@copilotkit/react-core"; // [!code highlight]
        import { useState } from 'react';

        export function YourComponent() {
            // Create colleagues state with some sample data
            const [colleagues, setColleagues] = useState([
                { id: 1, name: "John Doe", role: "Developer" },
                { id: 2, name: "Jane Smith", role: "Designer" },
                { id: 3, name: "Bob Wilson", role: "Product Manager" }
            ]);

            // Define Copilot readable state
            // [!code highlight:4]
            useCopilotReadable({
                description: "The current user's colleagues",
                value: colleagues,
            });
            return (
                // Your custom UI component
                <>...</>
            );
        }
        ```
    </Step>

    <Step>
        ### Consume the data in your AG-UI server
        The `context` you register on the frontend is forwarded to your AG-UI server in `ChatOptions.AdditionalProperties["ag_ui_context"]`. Use middleware to access this context and inject it into the agent's conversation.

        <Tabs groupId="language_microsoft-agent-framework_agent" items={['.NET', 'Python']} persist>
          <Tab value=".NET">
            ```csharp title="Program.cs"
            using System.Runtime.CompilerServices;
            using System.Text;
            using Azure.AI.OpenAI;
            using Azure.Identity;
            using Microsoft.Agents.AI;
            using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore;
            using Microsoft.AspNetCore.Builder;
            using Microsoft.Extensions.AI;

            var builder = WebApplication.CreateBuilder(args);
            builder.Services.AddAGUI();
            var app = builder.Build();

            string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]!;
            string deployment = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]!;

            // Create the base agent
            AIAgent baseAgent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
                .GetChatClient(deployment)
                .CreateAIAgent(
                    name: "AGUIAssistant",
                    instructions: "You are a helpful assistant. Use the provided context about colleagues to answer questions.");

            // Wrap the agent with middleware to inject context
            AIAgent agent = baseAgent
                .AsBuilder()
                .Use(runFunc: null, runStreamingFunc: InjectContextMiddleware)
                .Build();

            // Map the AG-UI endpoint
            app.MapAGUI("/", agent);
            await app.RunAsync();

            // Middleware to inject useCopilotReadable context as a system message
            async IAsyncEnumerable<AgentRunResponseUpdate> InjectContextMiddleware(
                IEnumerable<ChatMessage> messages,
                AgentThread? thread,
                AgentRunOptions? options,
                AIAgent innerAgent,
                CancellationToken cancellationToken)
            {
                // Extract context from AG-UI additional properties and inject if present
                if (options is ChatClientAgentRunOptions { ChatOptions.AdditionalProperties: { } properties } &&
                    properties.TryGetValue("ag_ui_context", out KeyValuePair<string, string>[]? context) &&
                    context?.Length > 0)
                {
                    var contextBuilder = new StringBuilder();
                    contextBuilder.AppendLine("The following context from the user's application is available:");
                    foreach (var item in context)
                    {
                        contextBuilder.AppendLine($"- {item.Key}: {item.Value}");
                    }

                    var contextMessage = new ChatMessage(
                        ChatRole.System,
                        [new TextContent(contextBuilder.ToString())]);

                    messages = messages.Append(contextMessage);
                }

                await foreach (var update in innerAgent.RunStreamingAsync(messages, thread, options, cancellationToken))
                {
                    yield return update;
                }
            }
            ```
          </Tab>
          <Tab value="Python">
            ```python title="agent/src/agent.py"

            from agent_framework import ChatAgent, ChatClientProtocol
            from agent_framework.ag_ui import AgentFrameworkAgent


            def create_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent:
                """
                Minimal agent for agent app context demo (frontend context is forwarded automatically).
                """
                base_agent = ChatAgent(
                    name="sample_agent",
                    instructions="You are a helpful assistant.",
                    chat_client=chat_client,
                )

                return AgentFrameworkAgent(
                    agent=base_agent,
                    name="CopilotKitMicrosoftAgentFrameworkAgent",
                    description="Assistant using app context forwarded from the frontend.",
                    require_confirmation=False,
                )
            ```
          </Tab>
        </Tabs>

        <Callout type="info">
          Context registered with `useCopilotReadable` is automatically forwarded by the AG-UI protocol in `ChatOptions.AdditionalProperties["ag_ui_context"]` as an array of key-value pairs (description → value). The middleware extracts and injects this context into the conversation.
        </Callout>

        <Callout type="tip">
          **Configuration & Error Handling**: This example uses environment variables for configuration. Set `AZURE_OPENAI_ENDPOINT` and `AZURE_OPENAI_DEPLOYMENT_NAME` via `appsettings.json`, user-secrets, or environment variables. For production deployments, add appropriate error handling and consider using the [Quickstart](/microsoft-agent-framework/quickstart) or [Authentication](/microsoft-agent-framework/auth) guides for complete setup patterns.
        </Callout>
    </Step>
    <Step>
        ### Give it a try!
        Ask your agent a question about the context (e.g., "Who are my colleagues?"). The agent will use the forwarded context to answer!
    </Step>
</Steps>
